package org.example;

import org.example.annotation.InitMethod;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.Properties;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args ){
        try {
            deputyMain("myapp.properties","bootstrapClass");
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public static Object deputyMain(String propertiesFileName,String refClassName) throws IOException {
        Properties appProperties = getProperties(propertiesFileName);
        try {
            String className = appProperties.getProperty(refClassName);
            return callInitMethod(className);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Properties getProperties(String propertiesFileName) throws IOException {
        Properties appProperties = new Properties();
        InputStream input = App.class.getClassLoader().getResourceAsStream(propertiesFileName);
        appProperties.load(input);
        return appProperties;
    }

    public static Object createInstance(String className) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class<?> clazz = Class.forName(className);
        return clazz.getDeclaredConstructor().newInstance();
    }

    public static Object callInitMethod(String className) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class myInitClass = Class.forName(className);
        Object myInitObject = createInstance(className);
        for (Method method : myInitClass.getDeclaredMethods()) {
            if (method.isAnnotationPresent(InitMethod.class)) {
                return method.invoke(myInitObject);
            }
        }
        return myInitObject;
    }
}
